package io.github.wppli.infrastructure.persistent.repository;

import io.github.wppli.domain.message.model.entity.PrivateMessageEntity;
import io.github.wppli.domain.message.model.entity.UserMessageEntity;
import io.github.wppli.domain.message.model.repository.IMessageRepository;
import io.github.wppli.infrastructure.persistent.dao.IPrivateMessageDao;
import io.github.wppli.infrastructure.persistent.dao.IUserDao;
import io.github.wppli.infrastructure.persistent.po.PrivateMessage;
import io.github.wppli.infrastructure.persistent.po.User;
import io.github.wppli.types.common.DateTimeUtils;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Repository;

import java.util.*;
import java.util.concurrent.ThreadPoolExecutor;

@Repository
@AllArgsConstructor
public class MessageRepository implements IMessageRepository {

    private final ThreadPoolExecutor executor;
    private final IPrivateMessageDao privateMessageDao;
    private final IUserDao userDao;

    @Override
    public void saveMessageAsync(PrivateMessageEntity privateMessageEntity) {
        executor.execute(() -> {
            // 查询用户名
            User user = userDao.queryUserInfoById(privateMessageEntity.getSenderId().toString());
            PrivateMessage privateMessage = PrivateMessage.builder()
                    .id(privateMessageEntity.getId())
                    .senderId(privateMessageEntity.getSenderId())
                    .receiverId(privateMessageEntity.getReceiverId())
                    .content(privateMessageEntity.getContent())
                    .isRead(0)
                    .isRetracted(0)
                    .sendTime(DateTimeUtils.stringToLocalDateTime(privateMessageEntity.getSendTime()))
                    .senderUserName(user.getUsername())
                    .build();
            privateMessageDao.insert(privateMessage);
        });
    }

    /**
     * 获取未读消息
     * @param receiverId 接收者id
     */
    @Override
    public List<UserMessageEntity> queryUnreadMessages(Long receiverId) {
        // 1. 查询给定接收者的发消息的用户
        List<UserMessageEntity> userMessageEntities = privateMessageDao.querySenderIds(receiverId);
        if (userMessageEntities.isEmpty()) {
            return Collections.emptyList();
        }
        // 2. 查出所有未读消息
        PrivateMessage privateMessage = PrivateMessage.builder().receiverId(receiverId)
                .isRead(0).isRetracted(0).build();
        List<PrivateMessage> privateMessages = privateMessageDao.queryUnreadMessages(privateMessage);
        List<PrivateMessageEntity> privateMessageEntities = new ArrayList<>();
        for (PrivateMessage message : privateMessages) {
            PrivateMessageEntity privateMessageEntity = PrivateMessageEntity.builder()
                    .id(message.getId())
                    .senderId(message.getSenderId())
                    .receiverId(message.getReceiverId())
                    .content(message.getContent())
                    .isRead(message.getIsRead() == 1)
                    .sendTime(DateTimeUtils.localDateTimeToString(message.getSendTime()))
                    .build();
            privateMessageEntities.add(privateMessageEntity);
        }
        // 3. 按照发送用户分类
        Map<Long, List<PrivateMessageEntity>> groupedMessages = new HashMap<>();
        for (PrivateMessageEntity message : privateMessageEntities) {
            Long senderId = message.getSenderId();
            groupedMessages.computeIfAbsent(senderId, k -> new ArrayList<>()).add(message);
        }
        // 4. 构造返回参数
        for (UserMessageEntity userMessageEntity : userMessageEntities) {
            List<PrivateMessageEntity> privateMessageEntityList = groupedMessages.getOrDefault(userMessageEntity.getUserId(), Collections.emptyList());
            userMessageEntity.setMessageList(privateMessageEntityList);
            userMessageEntity.setMessageCount(privateMessageEntityList.size());
        }
        return userMessageEntities;
    }

    @Override
    public void markMessageRead(Long receiverId, Long senderId) {
        privateMessageDao.updateMessagesRead(receiverId, senderId);
    }
}